home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Languages / MacGofer 0.22d / MacGofer Sources / mac_files.c < prev    next >
Encoding:
Text File  |  1994-04-08  |  37.5 KB  |  468 lines  |  [TEXT/MPS ]

  1. LSE))
  2.     return(windex);
  3.   else
  4.     return(ILLEGAL_WINDOW);
  5. }
  6.  
  7. /*
  8.   Revert a file from a saved copy.
  9.   Revert even if apparently unchanged -- this file may be shared!
  10. */
  11.  
  12. revert(windex)
  13. int windex;
  14. {
  15.   ioResult = noErr;
  16.  
  17.   if(revertdialog(FILENAME(windex)))
  18.     {
  19.       updatewindows();
  20.       TESetSelect(0,32767,TEHANDLE(windex));
  21.       TEDelete(TEHANDLE(windex));
  22.       (void) readtext(WINDOW(windex),FILENAME(windex),FALSE,TRUE);
  23.     }
  24. }
  25.  
  26.  
  27. /* Delete a file */ 
  28.  
  29. dodelete()
  30. {
  31.   char *file = deletedialog();
  32.   ioResult = noErr;
  33.  
  34.   if(*file != '\0')
  35.     (void) CheckError(file, ActionDelete,
  36.       hdelete(file,ReplySpec.vRefNum,ReplySpec.parID));
  37. }
  38.  
  39.  
  40.  
  41. /*
  42.   Read text from a file into a window.
  43. */
  44.  
  45.  
  46. int readtext(window,file,closeOnFail,showWin)
  47. WindowPtr window;
  48. char *file;
  49. Boolean closeOnFail, showWin;
  50. {
  51.   int windex = findMyWindow(window);
  52.   
  53.   if(!isLegalWindow(windex))
  54.     return(ILLEGAL_WINDOW);
  55.     
  56.   if(!doread(file,VREFNUM(windex),DIRID(windex),windex)  && closeOnFail)
  57.     {
  58.       CloseAWindow(windex);
  59.       return(ILLEGAL_WINDOW);
  60.     }
  61.   else
  62.     {
  63.       /* Do this even for partially read files */
  64.       AdjustScrollBars(windex);
  65.       ScrollToSelection(windex);
  66.       InvalRect(&(*TEHANDLE(windex))->viewRect);
  67.  
  68.       FLAGS(windex) &= ~WLOCKED;
  69.       if(fileIsLocked(FILENAME(windex),VREFNUM(windex),DIRID(windex),FALSE))
  70.         if (isUserLocked(FILENAME(windex),VREFNUM(windex),DIRID(windex)))
  71.            FLAGS(windex) |= WFLOCKED;
  72.     else
  73.            FLAGS(windex) |= WVLOCKED;
  74.  
  75.       if(showWin)
  76.         {
  77.           DrawControls(WINDOW(windex));
  78.           DrawGrowIcon(WINDOW(windex));
  79.           DrawGoferIcons(windex);
  80.           ShowWindow(WINDOW(windex));
  81.     }
  82.  
  83.       saved(windex);
  84.       MODTIME(windex) = getmodtime(FILENAME(windex),VREFNUM(windex),DIRID(windex));
  85.       return(windex);
  86.     }
  87. }
  88.  
  89. Handle ConvertTabs(teh,length,path)
  90. Handle teh;
  91. long length;
  92. short path;
  93. {
  94.   int i, j, oj;
  95.   int tabs=0, nl=0;
  96.   Handle nteh = NIL;
  97.   char ch;
  98.  
  99.   for(i=0;i < length; ++i)
  100.     if((char) *(*teh+i) == '\t')
  101.       ++tabs;
  102.  
  103.   if(tabs > 0)
  104.     {
  105.       nteh=NewHandle(length+tabs*8);
  106.       if(nteh==NIL)
  107.         {
  108.       if(path >= 0)
  109.         (void)FSClose(path);
  110.       AbortError("Memory ","Not enough memory to convert tabs in file");
  111.     }
  112.  
  113.       for(i=j=0;i<length;++i)
  114.         if((ch = (char) *(*teh+i)) == '\t')
  115.       for(oj=j;j < (oj + 8 - (oj - nl)%8);++j)
  116.         *(*nteh+j) = ' ';
  117.        
  118.     else if(ch == '\r' || ch == '\n')
  119.       {
  120.         *(*nteh+j++) = '\n';
  121.         nl = j;
  122.       }
  123.  
  124.     else
  125.       *(*nteh+j++) = *(*teh+i);
  126.  
  127.       SetHandleSize(nteh,j);
  128.       DisposeHandle(teh);
  129.       return(nteh);
  130.     }
  131.   else
  132.     return(teh);
  133. }
  134.  
  135.  
  136. /*
  137.     Read a file into a window.
  138. */
  139.  
  140. /* Was there an error? */
  141. #define CHECK_READ_ERROR(theResult)    CheckError(file, ActionOpen, theResult)
  142.  
  143. /* Uses CHECK_READ_ERROR to check for an error, and then closes the file and leaves the routine if necessary */
  144. #define HANDLE_READ_ERROR(theResult)    if (CHECK_READ_ERROR(theResult)) { if (path != 0) (void) FSClose(path); return(FALSE); }
  145.  
  146. doread(file,volnum,dirID,windex)
  147. char *file;
  148. short volnum;
  149. long dirID;
  150. int windex;
  151. {
  152.   short path = 0;
  153.   long length;
  154.   Handle textHandle;
  155.   long nread;
  156.   OSErr readResult;
  157.  
  158.   /* Open the file */
  159.   SetCursor(*watchcurs);
  160.   HANDLE_READ_ERROR( hopen(file,volnum,dirID,fsRdPerm,&path) );
  161.  
  162.   /* Get its length, and complain if it's too big */
  163.   HANDLE_READ_ERROR( GetEOF(path,&length) );
  164.   if(length > TE_REC_SIZE)
  165.     {
  166.       Complain(file,StringFileTooLarge);
  167.       (void) FSClose(path);
  168.       return(FALSE);
  169.     }
  170.  
  171.   if(MaxBlock() < length + 1024)
  172.     {
  173.       Error("Memory ","Not enough memory left to open file");
  174.       (void) FSClose(path);
  175.       return(FALSE);
  176.     }
  177.       
  178.  
  179.   /* Allocate a handle so we can read in the text */
  180.   textHandle = NewHandle(length);
  181.   if (textHandle == NIL)
  182.     HANDLE_READ_ERROR( MemError() );
  183.  
  184.   /* This seems much less reliable than the code below.  It doesn't
  185.      check for partial blocks read, it uses much more memory
  186.      (up to 32K rather than 1K maximum), and doesn't retry network
  187.      reads. It also definitely won't work when BigTextEdit is plugged in. KH
  188.   */
  189. updateFont(winfo,fontnum,mfinfop->fontsize);
  190.  
  191.       /* Restore the selection range */
  192.       TESetSelect((short)mfinfop->selStart,(short)mfinfop->selEnd,TEHANDLE(winfo));
  193.     }
  194.      
  195.  
  196.   /* EFNT 1003 takes priority over Gofer-specific info */   
  197.   if(mres == NIL)
  198.     fres = GetResource(FontInfoType,Res_FontInfo);
  199.  
  200.   /* Restore the font and size */
  201.   if(fres != NIL && (isEditWindow(winfo) || iconic(winfo)))
  202.     {
  203.       short fontnum;
  204.       HLock(fres);
  205.       efinfop = (FileFontInfo *) *fres;
  206.       GetFNum(efinfop->fontName,&fontnum);
  207.       if(fontnum != 0 && efinfop->fontSize > 0 && efinfop->fontSize < 256)
  208.     updateFont(winfo,fontnum,efinfop->fontSize);
  209.       HUnlock(fres);
  210.       DetachResource(fres);
  211.       DisposeHandle(fres);
  212.     }
  213.     
  214.   
  215.   gres = GetResource(GoferFileInfoType,Res_GoferFileInfo);
  216.   if(gres != NIL)
  217.     {
  218.       HLock(gres);
  219.       finfop = (GoferFileInfo *) *gres;
  220.       if(finfop->literate==1)
  221.         FLAGS(winfo) |= WLITERATE;
  222.       else
  223.         FLAGS(winfo) &= ~WLITERATE;
  224.   
  225.       if(finfop->hasknum==1)
  226.         FLAGS(winfo) |= WHNUM;
  227.       else
  228.         FLAGS(winfo) &= ~WHNUM;
  229.  
  230.  
  231.       if(mres == NIL && (isEditWindow(winfo) || iconic(winfo)))
  232.         {
  233.       char thefont[256];
  234.       getfontname(finfop->fontnum,thefont);
  235.  
  236.       /*
  237.          Check whether the saved font exists and is a sensible size,
  238.          and if so, set it for winfo's TE record
  239.       */
  240.  
  241.       if(fres == NIL && *thefont != '\0' && finfop->fontsize > 0 && finfop->fontsize < 256)
  242.         updateFont(winfo,finfop->fontnum,finfop->fontsize);
  243.  
  244.       /* Restore the selection range */
  245.       TESetSelect((short)finfop->selStart,(short)finfop->selEnd,TEHANDLE(winfo));
  246.         }
  247.  
  248.  
  249.       /* Restore the size and position of the window, if possible */
  250.       if(mres != NIL || finfop->infoversion > 0)
  251.         {
  252.       Rect pr = mres == NIL? finfop->portRect:mfinfop->shrunk;
  253.       
  254.       /* Sanity checks for off-screen windows */
  255.       if(pr.left >= qd.screenBits.bounds.right - 10 ||
  256.          pr.left <= qd.screenBits.bounds.left + 10)
  257.         {
  258.           pr.right -= pr.left;
  259.           pr.left = qd.screenBits.bounds.left + 10;
  260.           pr.right += pr.left;
  261.         }
  262.  
  263.       if(pr.right >= qd.screenBits.bounds.right - 10 || 
  264.          pr.right <=qd.screenBits.bounds.left + 10)
  265.         pr.right = qd.screenBits.bounds.right - 10;
  266.       
  267.       if(pr.top >= qd.screenBits.bounds.bottom - 10 ||
  268.          pr.top <= qd.screenBits.bounds.top + 10)
  269.         {
  270.           pr.bottom -= pr.top;
  271.           pr.top = qd.screenBits.bounds.top + 10;
  272.           pr.bottom += pr.top;
  273.         }
  274.  
  275.       if(pr.bottom >= qd.screenBits.bounds.bottom - 10 ||
  276.          pr.bottom <= qd.screenBits.bounds.top + 10)
  277.         pr.bottom = qd.screenBits.bounds.bottom - 10;
  278.       
  279.         MoveWindow(WINDOW(winfo), pr.left, pr.top, false);
  280.         SizeWindow(WINDOW(winfo), pr.right - pr.left, pr.bottom - pr.top, false);
  281.       ResizeTheWindow(WINDOW(winfo));
  282.  
  283.       /* Restore the icon window position if it's been saved */
  284.           if(finfop->infoversion > 1)
  285.             {
  286.           CreateIconWindow(winfo,FALSE);
  287.           pr = finfop->iconportRect;
  288.           
  289.           /* Sanity tests for icons -- 26 is a magic number */
  290.           if(pr.left >= qd.screenBits.bounds.right - 26)
  291.             {
  292.           pr.right -= pr.left;
  293.               pr.left = qd.screenBits.bounds.right - 26;
  294.           pr.right += pr.left;
  295.         }
  296.  
  297.           if(pr.left <= qd.screenBits.bounds.left + 26)
  298.             {
  299.           pr.right -= pr.left;
  300.               pr.left = qd.screenBits.bounds.left + 26;
  301.           pr.right += pr.left;
  302.         }
  303.         
  304.           if(pr.top >= qd.screenBits.bounds.bottom - 26)
  305.             {
  306.           pr.bottom -= pr.top;
  307.               pr.top = qd.screenBits.bounds.bottom - 26;
  308.           pr.bottom += pr.top;
  309.         }
  310.  
  311.           if(pr.top <= qd.screenBits.bounds.top + 26)
  312.             {
  313.           pr.bottom -= pr.top;
  314.               pr.top = qd.screenBits.bounds.top + 26;
  315.           pr.bottom += pr.top;
  316.         }
  317.         
  318.             MoveWindow(ICONWINDOW(winfo), pr.left, pr.top, false);
  319.         }
  320.     }
  321.  
  322.       HUnlock(gres);
  323.       HUnlock(mres);
  324.  
  325.       CloseResFile(path);
  326.       DetachResource(gres);
  327.       DisposeHandle(gres);
  328.       DetachResource(mres);
  329.       DisposeHandle(mres);
  330.     }
  331.   else
  332.     CloseResFile(path);
  333. }
  334.  
  335.  
  336. /*
  337.     Determine whether a file is literate by:
  338.     
  339.     1)    Checking the file information;
  340.     2)    Reading the first character.
  341. */
  342.  
  343. IsLiterateFile(volnum,dirID,file)
  344. short volnum;
  345. long dirID;
  346. char *file;
  347. {
  348.   short path;
  349.   Boolean result = FALSE;
  350.   
  351.   resolvealias(&file,&volnum,&dirID,FALSE);
  352.   
  353.   path = HOpenResFile(volnum,dirID,c2pstr(file),fsRdPerm);
  354.   
  355.   p2cstr(file);
  356.   if(path >= 0)
  357.     {
  358.       Handle gres = GetResource(GoferFileInfoType,Res_GoferFileInfo);
  359.  
  360.       if(gres != NIL)
  361.         {
  362.           result = ((GoferFileInfo *) *gres)->literate==1;
  363.           CloseResFile(path);
  364.           DetachResource(gres);
  365.           DisposeHandle(gres);
  366.        }
  367.       else
  368.         CloseResFile(path);
  369.     }
  370.  
  371.   /* Otherwise, check whether the first character is '>' */  
  372.   if(!result)
  373.     {
  374.       long length;
  375.       if(hopen(file,volnum,dirID,fsRdPerm,&path) == noErr)
  376.         {
  377.       if( GetEOF(path,&length) == noErr && length > 0)
  378.         {
  379.           char firstch;
  380.           length = 1;
  381.               if(FSRead(path,&length,(Ptr)(&firstch)) == noErr)
  382.             result = firstch == '>';
  383.         }
  384.        (void) FSClose(path);
  385.     }
  386.     }
  387.   return(result?1:0);
  388. }
  389.  
  390.  
  391. /*
  392.     Determine whether Haskell Numbers should be used for this file,
  393.     by reading the saved file information.
  394. */
  395.  
  396.  
  397. IsHaskNumFile(volnum,dirID,file)
  398. short volnum;
  399. long dirID;
  400. char *file;
  401. {
  402.   short path;
  403.   Boolean result = FALSE;
  404.   
  405.   resolvealias(&file,&volnum,&dirID,FALSE);
  406.   
  407.   path = HOpenResFile(volnum,dirID,c2pstr(file),fsRdPerm);
  408.  
  409.   p2cstr(file);
  410.   if(path >= 0)
  411.     {
  412.       Handle gres = GetResource(GoferFileInfoType,Res_GoferFileInfo);
  413.  
  414.       if(gres != NIL)
  415.         {
  416.           result = ((GoferFileInfo *) *gres)->hasknum==1;
  417.           CloseResFile(path);
  418.           DetachResource(gres);
  419.           DisposeHandle(gres);
  420.        }
  421.       else
  422.         CloseResFile(path);
  423.     }
  424.   return(result?1:0);
  425. }
  426.  
  427.  
  428. /*
  429.     Resolve a System 7 alias
  430. */
  431.  
  432.  
  433. static FSSpec fsspec;
  434. resolvealias(file,volnum,dirID,copyname)
  435. char    **file;
  436. long    *dirID;
  437. short   *volnum;
  438. Boolean copyname;
  439. {
  440.   /* Resolve an alias, perhaps */
  441.   if(systemVersion >= 0x0700)
  442.      {
  443.     Boolean wasFolder, wasAliased;
  444.  
  445.         fsmakefsspec(*file,*volnum,*dirID,&fsspec);
  446.         ResolveAliasFile(&fsspec,TRUE,&wasFolder,&wasAliased);
  447.     
  448.     if(wasFolder)
  449.       return;
  450.  
  451.         if(wasAliased)
  452.       {
  453.             /* Copy the resolved alias */
  454.         if(copyname)
  455.           {
  456.             *file = safemalloc((int)(fsspec.name[0])+1);
  457.             pstrcopy(fsspec.name,*file);
  458.               }
  459.         else
  460.           *file = (char *)fsspec.name;
  461.  
  462.         p2cstr(*file);
  463.         *volnum =  fsspec.vRefNum;
  464.         *dirID =   fsspec.parID;
  465.       }
  466.     }
  467. }
  468.